#coding=utf-8
# !/usr/bin/python
# -*- coding: utf-8 -*-
from ctypes import *
from dt_ui_mplot import *
import matplotlib
import numpy as np
from PySide6 import QtWidgets 
#from PySide6.QtWidgets import QGridLayout

import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar

class c_highspeed:
    def __init__(self, ui):
        self.ui = ui
        self.com = ui.com
        self.a_pe = []
        self.a_pec = []
        self.a_mspeed = []
        self.a_mpos = []
        self.a_rpos = []
        self.a_new = []

        self.ga_x = [] # 起始点x
        self.ga_pe = [] # 起始点y
        self.ga_pec = [] # 起始点y
        self.ga_mspeed = [] # 起始点y
        self.ga_new = [] # 
        self.ga_mpos = [] # 起始点y
        self.ga_rpos = [] # 起始点y
        self.dt_xmax = 16000
        self.dt_framelen = 15
        self.frame_num = 0
        self.x_idx = 0
        self.setup_plot()
        self.user_setup_ui()




    def setup_plot(self):
        self.phase_fig = c_Mplplot(width=5, height=3, dpi=72)
        self.fig_ntb = NavigationToolbar(self.phase_fig, self.ui)
        self.gridlayout = QtWidgets.QGridLayout(self.ui.groupBox_5)
        self.gridlayout.addWidget(self.phase_fig)
        self.gridlayout.addWidget(self.fig_ntb)
        x_data = np.arange(0, 0.1, 0.1)
        y_data = np.repeat(0, 1)
        self.phase_fig.add_line(1000, x_data, y_data)
        
        
    def find_head(self, a):
        i = 0
        data_len = self.dt_framelen - 1
        while i < self.dt_framelen:    
            if a[i] == 0xA0 and a[i + data_len] == 0x0A:
                return i
            i+=1
        return 0

    def handle_data(self, a_pe, a_pec, a_mspeed, a_mpos, a_rpos, a_new):
  
        ret = 0
        
        if 0 != len(a_pe):
            for i in range(0, len(a_pe)):
                self.ga_x.append( (i + self.x_idx)/1000 )
            self.x_idx+=  len(a_pe) 
            self.ga_pe+= a_pe
            self.ga_pec+= a_pec
            self.ga_mspeed+= a_mspeed
            self.ga_mpos+= a_mpos
            self.ga_rpos+= a_rpos
            self.ga_new+= a_new
            del_len = len(self.ga_pe) - self.dt_xmax
            if del_len > 0 :
                self.ga_x = self.ga_x[del_len:]
                self.ga_pe = self.ga_pe[del_len:]
                self.ga_pec = self.ga_pec[del_len:]
                self.ga_mspeed = self.ga_mspeed[del_len:]
                self.ga_mpos = self.ga_mpos[del_len:]
                self.ga_rpos = self.ga_rpos[del_len:]
                self.ga_new = self.ga_new[del_len:]
            if del_len != 0 :    
                ret = 1
        return ret
 

    def parse_frame(self, h):
        pe = ( (h[2] << 8) + h[3] )
        pec = ( (h[4] << 8) + h[5])
        speed = ( (h[6] << 8) + h[7])
        new = ( (h[8] << 8) + h[9])
        disp = ( (h[10] << 8) + h[11]) 
        rdisp = ( (h[12] << 8) + h[13]) 
        
        self.a_pe.append(c_int16(pe).value)
        self.a_pec.append(c_int16(pec).value)
        self.a_mspeed.append(c_int16(speed).value)
        self.a_mpos.append(c_int16(disp).value)
        self.a_rpos.append(c_int16(rdisp).value)
        self.a_new.append(c_int16(new).value)


    def parse_block(self, h):
        data_len = self.dt_framelen - 1
        i = 0
        err = 0
        frame = 0
        self.a_pe.clear()
        self.a_pec.clear()
        self.a_mspeed.clear()
        self.a_mpos.clear()
        self.a_rpos.clear()
        self.a_new.clear()
        while i < len(h) - data_len :
            if h[i] == 0xA0 and h[i + data_len] == 0x0A:      
                self.frame_num = self.frame_num + 1
                self.parse_frame(h[i:i + data_len])
                i+= self.dt_framelen
                frame+= 1
            else:
                i+=1
                err+=1   
        #if (len(h) - i) != 0:
        #    print("frame left", len(h) - i) 
        self.handle_data(self.a_pe, self.a_pec, self.a_mspeed, self.a_mpos, self.a_rpos, self.a_new)
        self.update_data_thread_slot() 
        return (len(h) - i)
        
    def user_setup_ui(self):

        self.ui.cmsel2.stateChanged.connect(self.cmsel2_cb)
        self.ui.cmsel2_2.stateChanged.connect(self.cmsel2_2_cb)
        self.ui.pushButton_16.clicked.connect(self.pushButton_16_cb)
        
        # 配置数据选择项
        self.ui.data_sel1.setChecked(bool(self.ui.cfg.data['dsel'][0]))
        self.ui.data_sel2.setChecked(bool(self.ui.cfg.data['dsel'][1]))
        self.ui.data_sel3.setChecked(bool(self.ui.cfg.data['dsel'][2]))
        self.ui.data_sel4.setChecked(bool(self.ui.cfg.data['dsel'][3]))
        self.ui.data_sel5.setChecked(bool(self.ui.cfg.data['dsel'][4]))
        self.ui.data_sel6.setChecked(bool(self.ui.cfg.data['dsel'][5]))

        # 配置数据放大倍数
        self.ui.ddvi1.setCurrentIndex(self.ui.cfg.data['ddiv'][0])
        self.ui.ddvi2.setCurrentIndex(self.ui.cfg.data['ddiv'][1])
        self.ui.ddvi3.setCurrentIndex(self.ui.cfg.data['ddiv'][2])
        self.ui.ddvi4.setCurrentIndex(self.ui.cfg.data['ddiv'][3])
        self.ui.ddvi5.setCurrentIndex(self.ui.cfg.data['ddiv'][4])
        self.ui.ddvi6.setCurrentIndex(self.ui.cfg.data['ddiv'][5])

        self.ui.data_sel1.stateChanged.connect(self.data_selecter)
        self.ui.data_sel2.stateChanged.connect(self.data_selecter)
        self.ui.data_sel3.stateChanged.connect(self.data_selecter)
        self.ui.data_sel4.stateChanged.connect(self.data_selecter)
        self.ui.data_sel5.stateChanged.connect(self.data_selecter)
        self.ui.data_sel6.stateChanged.connect(self.data_selecter)

        
        self.ui.ddvi1.currentIndexChanged.connect(self.data_dvicb)
        self.ui.ddvi2.currentIndexChanged.connect(self.data_dvicb)
        self.ui.ddvi3.currentIndexChanged.connect(self.data_dvicb)
        self.ui.ddvi4.currentIndexChanged.connect(self.data_dvicb)
        self.ui.ddvi5.currentIndexChanged.connect(self.data_dvicb)

    def pushButton_16_cb(self):
        self.ui.cfg.save()

    def cmsel2_cb(self):
        if self.com.serdev.ser.isOpen():
            array = self.com.pack_frame_head(0x24, 0x30)
            if self.ui.cmsel2.isChecked():
                array[37] = 1
                self.ui.com.dump_en = True
            else:
                array[37] = 2
                self.ui.com.dump_en = False
            self.com.pack_frame_tail(array)
            self.com.serdev.ser.write(array)
        else:
            pass

            
    def cmsel2_2_cb(self):
        self.ui.com.timer_disable = self.ui.cmsel2_2.isChecked()
        
    def data_dvicb(self, arg):
        self.ui.cfg.data['ddiv'][0] = (self.ui.ddvi1.currentIndex())
        self.ui.cfg.data['ddiv'][1] = (self.ui.ddvi2.currentIndex())
        self.ui.cfg.data['ddiv'][2] = (self.ui.ddvi3.currentIndex())
        self.ui.cfg.data['ddiv'][3] = (self.ui.ddvi4.currentIndex())
        self.ui.cfg.data['ddiv'][4] = (self.ui.ddvi5.currentIndex())
        self.ui.cfg.data['ddiv'][5] = (self.ui.ddvi6.currentIndex())
        # 更新数据
        self.update_data_thread_slot()
        
        # 数据选择控件回调
    def data_selecter(self, arg):
        if self.ui.data_sel1.isChecked():
            self.ui.cfg.data['dsel'][0] = 1
        else:
            self.ui.cfg.data['dsel'][0] = 0
            
        if self.ui.data_sel2.isChecked():
            self.ui.cfg.data['dsel'][1] = 1
        else:
            self.ui.cfg.data['dsel'][1] = 0
            
        if self.ui.data_sel3.isChecked():
            self.ui.cfg.data['dsel'][2] = 1
        else:
            self.ui.cfg.data['dsel'][2] = 0
            
        if self.ui.data_sel4.isChecked():
            self.ui.cfg.data['dsel'][3] = 1
        else:
            self.ui.cfg.data['dsel'][3] = 0
            
        if self.ui.data_sel5.isChecked():
            self.ui.cfg.data['dsel'][4] = 1
        else:
            self.ui.cfg.data['dsel'][4] = 0 
            
        if self.ui.data_sel6.isChecked():
            self.ui.cfg.data['dsel'][5] = 1
        else:
            self.ui.cfg.data['dsel'][5] = 0   
        # 更新数据    
        self.update_data_thread_slot()    
        
    def ui_pushButton1_cb(self):
        if self.com.serdev.ser.isOpen():
            array = self.com.pack_frame_head(0x24, 0x30)
            self.pack_matain_msg(array)
            self.com.pack_frame_tail(array)
            self.com.serdev.ser.write(array)
            print(' '.join(f'{c:02x}' for c in array))
        else:
            pass  
        
    def update_data_thread_slot(self):
        
        if len(self.ga_x) == 0: 
            return
        
        dotlist = [0.01, 0.1, 1, 10, 100]
        da1 = np.dot(self.ga_pe, dotlist[self.ui.cfg.data['ddiv'][0]])
        da2 = np.dot(self.ga_pec, dotlist[self.ui.cfg.data['ddiv'][1]])
        da3 = np.dot(self.ga_mspeed, dotlist[self.ui.cfg.data['ddiv'][2]])
        da4 = np.dot(self.ga_new, dotlist[self.ui.cfg.data['ddiv'][3]])
        da5 = np.dot(self.ga_mpos, dotlist[self.ui.cfg.data['ddiv'][4]])
        da6 = np.dot(self.ga_rpos, dotlist[self.ui.cfg.data['ddiv'][5]])
        maxy = 0
        miny = 100000
        
        if self.ui.cfg.data['dsel'][0] == 1:
            # 更新lin1数据
            if len(da1) == len(self.ga_x):
                self.phase_fig.line1.set_ydata( da1 )
                self.phase_fig.line1.set_xdata(self.ga_x)
                maxy = max(maxy, np.max(da1))
                miny = min(miny, np.min(da1))
        else:
            self.phase_fig.line1.set_ydata( [] )
            self.phase_fig.line1.set_xdata( [] )
            
        if self.ui.cfg.data['dsel'][1] == 1:
            if len(da2) == len(self.ga_x):
                self.phase_fig.line2.set_ydata( da2 )
                self.phase_fig.line2.set_xdata(self.ga_x)
                maxy = max(maxy, np.max(da2))
                miny = min(miny, np.min(da2))
        else:
            self.phase_fig.line2.set_ydata( [] )
            self.phase_fig.line2.set_xdata( [] )

        if self.ui.cfg.data['dsel'][2] == 1:
            if len(da3) == len(self.ga_x):
                self.phase_fig.line3.set_ydata( da3 )
                self.phase_fig.line3.set_xdata(self.ga_x)
                maxy = max(maxy, np.max(da3))
                miny = min(miny, np.min(da3))
        else:
            self.phase_fig.line3.set_ydata( [] )
            self.phase_fig.line3.set_xdata( [] )

        if self.ui.cfg.data['dsel'][3] == 1:
            if len(da4) == len(self.ga_x):
                self.phase_fig.line4.set_ydata( da4 )
                self.phase_fig.line4.set_xdata(self.ga_x)
                maxy = max(maxy, np.max(da4))
                miny = min(miny, np.min(da4))
        else:
            self.phase_fig.line4.set_ydata( [] )
            self.phase_fig.line4.set_xdata( [] )

        if self.ui.cfg.data['dsel'][4] == 1:
            if len(da5) == len(self.ga_x):
                self.phase_fig.line5.set_ydata( da5 )
                self.phase_fig.line5.set_xdata(self.ga_x)
                maxy = max(maxy, np.max(da5))
                miny = min(miny, np.min(da5))
        else:
            self.phase_fig.line5.set_ydata( [] )
            self.phase_fig.line5.set_xdata( [] )   
            
        if self.ui.cfg.data['dsel'][5] == 1:
            if len(da6) == len(self.ga_x):
                self.phase_fig.line6.set_ydata( da6 )
                self.phase_fig.line6.set_xdata(self.ga_x)
                maxy = max(maxy, np.max(da6))
                miny = min(miny, np.min(da6))
        else:
            self.phase_fig.line6.set_ydata( [] )
            self.phase_fig.line6.set_xdata( [] ) 

        ymax_int = int(maxy)
        ymin_int = int(miny)
        #ymax_int = (ymax_int+99)*100/100
        #ymin_int = (ymin_int-99)*100/100
        ymax_int = (ymax_int+49)*50/50
        ymin_int = (ymin_int-49)*50/50
        
        xlim0 = np.min(self.ga_x)
        xlim1 = np.max(self.ga_x)
        
        if xlim1 < self.dt_xmax/1000:
            xlim1 = self.dt_xmax/1000
            
        self.phase_fig.axes.set_xlim(xlim0, xlim1) 
        self.phase_fig.axes.set_ylim(ymin_int, ymax_int) 
        self.phase_fig.draw()  # 重新画图

